Basic Plot Befehl in Assembler

← Zurück zum Forum

Das wollte ich schon immer haben ... also muss ich es hier jetzt mal machen! Mithilfe, Optimierung und Ideen wie immer sehr willkommen.

Vorgabe: Antic D (Graphics 7), Auflösung 160x80 mit 3 (4) Farben. Die Routine soll möglichst schlank und schnell sein.

Drei Variablen: varx , vary, varcolor

AntwortZitat

Ich fange mal an: Zunächst die größte Schwierigkeit ist ja, daß man von den werten x=0 bis x=159 auf 0-39 kommen muss. Das klingt zunächst ja recht einfach, ich muss lediglich durch 4 teilen und das ist zum Glück wirklich sehr einfach. Allerdings muss man dann ja aber genau wissen, ob ich nach der Teilung Bit 1/2/3oder 4 setzen muss (in Abhängigkeit der Farbe). Man könnte jetzt eine Tabelle für alle drei Farben machen und jedem Wert von 0-159 das entsprechende Bit zuordnen - das wäre wohl der schnellste Weg, frisst aber Speicher. Das Atari Basic löst das ganz sicher anders... Meine Lösung wäre nun folgende: Ich mache 2x einen Shift nach rechts (also teile durch 4) mit LSR und addiere das Carry nach dem ersten Shift 1x zu einer Variablen und nach dem 2. Shift 2x zu einer Variablen. Die Variable hat dann nach dem 2. Shift die Werte 0,1,2 oder 3 was gleichzeitig die Position des zu setzenden Bits entspricht an der x-Position was nach dem Teilen durch 4 herauskommt. Beispiel x-Wert 53: 1. Shift: LSR 55 = 27 / Variable + Carry=1 2. Shift: LSR 27 = 13 / Variable + Carry + Carry=3

Das Bit wird also dann an der Bildschirmposition 13 geplottet, Bit 3 wird gesetzt

AntwortZitat

Also eine kleine Korrektur zum Verständnis: Mit Bit 0 meine ich das ganz Linke und mit Bit 3 das ganz Rechte... ist natürlich wenn ich es so schreibe unverständlich!

AntwortZitat

und hier die entsprechende Routine:

            org $4000   

bs1 = 250       ; Page 0 Variable           

xwert           .by 00
ywert           .by 00
varx            .by 00
posx            .by 00
wert            .by 00
color           .by 00

xconvert
            .byte 64,16,4,1     ; Farbe 1
            .byte 128,32,8,2    ; Farbe 2
            .byte 192,48,12,3   ; Farbe 3

            ;----------------- Gr. 7 BS Start bei 36960 ---------
dlist
            .byte 112,112,112
            .byte 77,96,144
:79         .byte 13
            .byte 66,96,159
            .byte 2,2,2
            .byte 65
            .word dlist
            ;------------ Textstart bei 40800 -------------------


            .proc main

            mwa #dlist 560

            ;-------------- Start Hauptprogramm -----------------------------   


            mwa #36920 bs1      ; Start Bildschirmspeicher

            mva #77 xwert       ; Punkt (x-Wert)
            mva #33 ywert       ; Punkt (y-Wert)
            mva #4 color        ; Farbe 2 wird hier initialisiert
            mva xwert varx

@
            clc
            lda bs1
            adc #40
            sta bs1
            lda bs1+1
            adc #0
            sta bs1+1
            dec ywert
            bne @-

            clc
            lda varx
            lsr
            sta varx
            bcc @+
            inc posx
@           
            lda varx
            lsr
            sta varx
            bcc @+
            inc posx
            inc posx
@           
            clc
            lda posx
            adc color
            tax
            lda xconvert,x
            sta wert

            ldy varx
            lda (bs1),y
            eor wert
            sta (bs1),y


            jmp *

            .endp

Diese Routine plottet einen Punkt exemplarisch (77/33) bei Graphics 7 auf den Bildschirm!

AntwortZitat

... Optimierungen welcome ... 😉

Die y-Spalten habe ich für dieses Beispiel extra mit eine (+40) Schleife berechnen lassen. Schneller ginge das natürlich mit einer Tabelle - und im normalen Spiel würde ich das auch entsprechend mit einer Tabelle machen!

AntwortZitat

Hallo!


    ldy varx
    lda (bs1),y
    eor wert
    sta (bs1),y

Würde immer nur Bits hinzuaddieren, aber nicht mehr löschen. Man könnte somit nicht die Farbe ändern oder gar auf 0 setzen. Man sollte vorm "eor" noch ein "and" setzen mit einer Maske, der die Bits des Pixels löscht.

Grüße Janko

Meine Projekte findest Du hier...

AntwortZitat

Hallo!

Hier einmal eine angepasste Version, wo ich die Maske nutze. Das erste Pixel wird mit dem 4. Pixel überschrieben:

            org $4000   

bs1 = 250       ; Page 0 Variable           

xwert           .by 00
ywert           .by 00
varx            .by 00
posx            .by 00
wert            .by 00
color           .by 00

xconvert
            .byte 64,16,4,1     ; Farbe 1
            .byte 128,32,8,2    ; Farbe 2
            .byte 192,48,12,3   ; Farbe 3

            ;----------------- Gr. 7 BS Start bei 36960 ---------
dlist
            .byte 112,112,112
            .byte 77,96,144
:79         .byte 13
            .byte 66,96,159
            .byte 2,2,2
            .byte 65
            .word dlist
            ;------------ Textstart bei 40800 -------------------


            .proc main

            mwa #dlist 560

            ;-------------- Start Hauptprogramm -----------------------------   


            mva #77 xwert       ; Punkt (x-Wert)
            mva #33 ywert       ; Punkt (y-Wert)
            mva #3 color        ; Farbe 3 
            jsr setpixel

            mva #76 xwert       ; Punkt (x-Wert)
            mva #33 ywert       ; Punkt (y-Wert)
            mva #2 color        ; Farbe 2 
            jsr setpixel

            mva #76 xwert       ; Punkt (x-Wert)
            mva #32 ywert       ; Punkt (y-Wert)
            mva #1 color        ; Farbe 1 
            jsr setpixel

            mva #77 xwert       ; Punkt (x-Wert)
            mva #33 ywert       ; Punkt (y-Wert)
            mva #1 color        ; Farbe 1 --> Pixles mit Farbe 3 wird überschrieben
            jsr setpixel

            jmp *

            .endp

            .proc setpixel

            mwa #36920 bs1      ; Start Bildschirmspeicher
@
            clc
            lda bs1
            adc #40
            sta bs1
            lda bs1+1
            adc #0
            sta bs1+1
            dec ywert
            bne @-

            clc
            lda xwert
            and #%00000011      ; untern 2 Bits retten
            tax
            lda xwert
            lsr
            lsr         ; durch 4 teilen
            tay

            lda (bs1),y
            and COLOR0,X

            lda color
            beq setpixel        ; Farbe 0 = löschen = fertig
            cmp #1
            bne @+          ; nicht Farbe 1 dann weiter
            lda COLOR1,X
            jmp setpixel
@           cmp #2
            bne @+          ; nicht Farbe 2 dann weiter
            lda COLOR2,X
            jmp setpixel
@           lda COLOR3,X            

setpixel        eor (bs1),y
            sta (bs1),y


            rts

COLOR0          dta $3F,$CF,$F3,$FC
COLOR1          dta $40,$10,$04,$01         
COLOR2          dta $80,$20,$08,$02         
COLOR3          dta $C0,$30,$0C,$03         
            .endp
            run main

Grüße Janko

Meine Projekte findest Du hier...

AntwortZitat

meine Lösung wäre jetzt diese:

            org $4000   

bs1 = 250       ; Page 0 Variable           

xwert           .by 00
ywert           .by 00
varx            .by 00
posx            .by 00
wert            .by 00
color           .by 00


xconvert
            .byte 64,16,4,1     ; Farbe 1
            .byte 128,32,8,2    ; Farbe 2
            .byte 192,48,12,3   ; Farbe 3

            ;----------------- Gr. 7 BS Start bei 36960 ---------
dlist
            .byte 112,112,112
            .byte 77,96,144
:79         .byte 13
            .byte 66,96,159
            .byte 2,2,2
            .byte 65
            .word dlist
            ;------------ Textstart bei 40800 -------------------


            .proc main

            mwa #dlist 560

            ;-------------- Start Hauptprogramm -----------------------------   


            mwa #36920 bs1      ; Start Bildschirmspeicher

            mva #1 xwert        ; Punkt (x-Wert)
            mva #1 ywert        ; Punkt (y-Wert)
            mva #4 color        ; Farbe 2 wird hier initialisiert
            mva xwert varx

@
            clc
            lda bs1
            adc #40
            sta bs1
            lda bs1+1
            adc #0
            sta bs1+1
            dec ywert
            bne @-

            clc
            lda varx
            lsr
            sta varx
            bcc @+
            inc posx
@           
            lda varx
            lsr
            sta varx
            bcc @+
            inc posx
            inc posx
@           
            clc
            lda posx
            adc color
            tax
            lda xconvert,x
            sta wert

            ldy varx
            lda (bs1),y

            ldx posx
            cpx #0
            bne @+
            rol
            clc
            rol
            clc
            ror
            ror
            jmp print
@           cpx #1
            bne @+
            rol
            rol
            rol
            clc
            rol
            clc
            ror
            ror
            ror
            ror
            jmp print
@
            cpx #2
            bne @+
            ror
            ror
            ror
            clc
            ror
            clc
            rol
            rol
            rol
            rol
            jmp print
@
            ror
            clc
            ror
            clc
            rol
            rol
print           
            eor wert
            sta (bs1),y


            jmp *

            .endp

... etwas mehr Code vielleicht, aber vielleicht schneller, da die ROL/ROR jeweils nur 2 Taktzyklen brauchen - habe es aber auch nicht ausgerechnet, Jankos Lösung ist in jedem Fall eleganter... 😉

AntwortZitat

das hat mir jetzt keine Ruhe gelassen... hier der Code mit Maske, ohne die Shifts...

            org $4000   

bs1 = 250       ; Page 0 Variable           

xwert           .by 00
ywert           .by 00
varx            .by 00
posx            .by 00
wert            .by 00
color           .by 00

maske           
            .byte 63,207,243,252


xconvert
            .byte 64,16,4,1     ; Farbe 1
            .byte 128,32,8,2    ; Farbe 2
            .byte 192,48,12,3   ; Farbe 3

            ;----------------- Gr. 7 BS Start bei 36960 ---------
dlist
            .byte 112,112,112
            .byte 77,96,144
:79         .byte 13
            .byte 66,96,159
            .byte 2,2,2
            .byte 65
            .word dlist
            ;------------ Textstart bei 40800 -------------------


            .proc main

            mwa #dlist 560

            ;-------------- Start Hauptprogramm -----------------------------   

            mwa #36920 bs1


            mva #0 xwert        ; Punkt (x-Wert)
            mva #1 ywert        ; Punkt (y-Wert)
            mva #0 color        ; Farbe 1
            ;mva #4 color       ; Farbe 2
            ;mva #8 color       ; Farbe 3
            mva xwert varx

@
            clc
            lda bs1
            adc #40
            sta bs1
            lda bs1+1
            adc #0
            sta bs1+1
            dec ywert
            bne @-

            clc
            lda varx
            lsr
            sta varx
            bcc @+
            inc posx
@           
            lda varx
            lsr
            sta varx
            bcc @+
            inc posx
            inc posx
@           
            clc
            lda posx
            adc color
            tax
            lda xconvert,x
            sta wert
            ldy varx
            lda (bs1),y
            ldx posx
            and maske,x
            eor wert
            sta (bs1),y


            jmp *


            .endp


            run main
AntwortZitat

Ich hab da zwar nicht viel verstanden, aber ohne die ROL/ROR sieht das übersichtlicher aus. Wenn man das nur ein ROL vergisst, RORtiert das ganze Programm 😁 Obs schneller ist, müsste man testen. Aber da sieht man mal wieder was für einen Aufwand man für ein einzelnes Pünktchen treiben kann. Gruß und viel Spass beim weiter optimieren. Ist sehr spannend 😀 Wolfgang

AntwortZitat